using System;
using Xunit;

namespace SmartSite.Frame.Test
{
    public class TestIdentityReqFrame
    {
        public IdentityReqFrame Build()
        {
            IdentityReqFrame frame = new IdentityReqFrame();
            frame.FactoryCode.Value = 4;
            frame.MonitorDeviceId.Value = "5678";
            frame.UserName.Value = "ljt";
            frame.PWD.Value = "asdfg";
            return frame;
        }

        [Fact]
        public void TestStruct()
        {

            IdentityReqFrame frame = Build();

            Assert.Equal(85, frame.Buffer.Count);
            Assert.Equal(3 * 8, (int)frame.MonitorDeviceId.Index);
            Assert.Equal(16 * 8, (int)frame.MonitorDeviceId.Count);
            Assert.Equal(19 * 8, (int)frame.UserName.Index);
            Assert.Equal(32 * 8, (int)frame.UserName.Count);
            Assert.Equal(51 * 8, (int)frame.PWD.Index);
            Assert.Equal(32 * 8, (int)frame.PWD.Count);
            Assert.Equal(83 * 8, (int)frame.CRC.Index);
            Assert.Equal(2 * 8, (int)frame.CRC.Count);

        }

        /// <summary>
        /// 与原版对比
        /// </summary>
        [Fact]
        public void TestOriginFrameComparison()
        {
            IdentityReqFrame frame = Build();
            frame.CRC.Value = frame.CalculationCRC();

            // 原版
            byte[] originalIdentityReqFrame = UDP_IDENTITY_REQFrame("5678");

            Assert.Equal(originalIdentityReqFrame, frame.Buffer);
        }




        /// <summary>
        /// 原版代码
        /// </summary>
        /// <param name="hardwareserialnum"></param>
        /// <returns></returns>s
        private byte[] UDP_IDENTITY_REQFrame(string hardwareserialnum)//身份验证请求帧
        {
            byte[] udpsendbuf = new byte[85];
            UInt16 UDP_IDENTITY_REQ = 0;
            byte MCODE = 0x44;


            for (int i = 0; i < udpsendbuf.Length; i++)
            {
                udpsendbuf[i] = 0;
            }
            udpsendbuf[0] = MCODE;//高4bit为协议版本，固定为0x04；低4bit为厂家代码，0-3保留，4～15用于区分不同厂家

            UInt16 stemp = UDP_IDENTITY_REQ;
            stemp = (UInt16)(stemp << 11);  //帧类型 ，占5bit 高字节
            stemp += 64;                    //数据长度,32字节的用户名和32字节的密码
            udpsendbuf[2] = (byte)stemp;    //信息长度 64，占11bit
            stemp = (UInt16)(stemp >> 8);
            udpsendbuf[1] = (byte)stemp;

            //byte[] hardwareID = uartanalys.strToToHexByte(basicpara.hardwareserialnum);
            //for (int i = 0; i < 16; i++)//固定16个字节
            //{
            //    udpsendbuf[3 + i] = hardwareID[i];
            //}
            // byte[] arrByte1 = System.Text.Encoding.GetEncoding("GB2312").GetBytes(hardwareserialnum);
            byte[] arrByte1 = System.Text.Encoding.ASCII.GetBytes(hardwareserialnum);
            arrByte1.CopyTo(udpsendbuf, 3);//定义设备代码占用16字节,16Bytes在身份验证请求时使用，其余情况下使用3Bytes，3Bytes登录后由服务器分配，作为通信ID

            // byte[] arrByte2 = System.Text.Encoding.GetEncoding("GB2312").GetBytes("ljt");
            byte[] arrByte2 = System.Text.Encoding.ASCII.GetBytes("ljt");
            arrByte2.CopyTo(udpsendbuf, 3 + 16);//用户名占用32字节

            byte[] arrByte3 = System.Text.Encoding.ASCII.GetBytes("asdfg");
            arrByte3.CopyTo(udpsendbuf, 3 + 16 + 32);//密码占用32字节

            UInt16 temp = crc16_calculate(udpsendbuf, 83);//3+16+32+32
            udpsendbuf[84] = (byte)temp; temp = (UInt16)(temp >> 8);
            udpsendbuf[83] = (byte)temp;

            stemp = 85;
            //uartanalys.hex_to_uart_pkt(ref udpsendbuf, ref stemp);
            // Udp_Send(udpsendbuf, stemp);//以太 udp 发送

            return udpsendbuf;
        }

        /// <summary>
        /// 原版代码
        /// </summary>
        /// <param name="pucSendBuf"></param>
        /// <param name="usLen"></param>
        /// <returns></returns>
        public UInt16 crc16_calculate(byte[] pucSendBuf, UInt16 usLen)
        {
            UInt16 usCrc = 0xFFFF;

            for (UInt16 i = 0; i < usLen; i++)
            {
                usCrc ^= (UInt16)pucSendBuf[i];
                for (UInt16 j = 0; j < 8; j++)
                {
                    if ((usCrc & 1) != 0)
                    {
                        usCrc >>= 1;
                        usCrc ^= 0xA001;
                    }
                    else
                    {
                        usCrc >>= 1;
                    }
                }
            }

            return usCrc;
        }

    }
}